from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from django.utils import timezone
from django.db import models

from django.db.models import Q
import yaml
import json
from django.contrib.auth.models import User
from rest_framework.views import APIView
from .models import Environment, TestCase, TestExecution, TestReport, DailyLog
from .serializers import (
    EnvironmentSerializer, TestCaseSerializer,
    TestExecutionSerializer, TestReportSerializer, TestCaseDetailSerializer, DailyLogSerializer
)
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth import authenticate
from rest_framework_simplejwt.tokens import RefreshToken

from .test_runner import TestRunner


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    def validate(self, attrs):
        data = super().validate(attrs)
        # 添加用户信息到响应中
        data['user'] = {
            'id': self.user.id,
            'username': self.user.username,
            'email': self.user.email,
            'first_name': self.user.first_name,
            'last_name': self.user.last_name,
        }
        return data


class CustomTokenObtainPairView(TokenObtainPairView):
    serializer_class = CustomTokenObtainPairSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            return Response(serializer.validated_data, status=status.HTTP_200_OK)
        else:
            return Response({
                'error': '用户名或密码错误'
            }, status=status.HTTP_400_BAD_REQUEST)


class EnvironmentViewSet(viewsets.ModelViewSet):
    """环境管理视图集"""
    queryset = Environment.objects.all()
    serializer_class = EnvironmentSerializer
    permission_classes = [AllowAny]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['is_active']
    search_fields = ['name', 'description']
    ordering_fields = ['name', 'created_at']
    ordering = ['-created_at']

    def create(self, request, *args, **kwargs):
        print("Received data:", request.data)
        return super().create(request, *args, **kwargs)

    @action(detail=False, methods=['post'])
    def validate_yaml(self, request):
        """验证环境YAML配置"""
        yaml_content = request.data.get('yaml_config', '')

        if not yaml_content.strip():
            return Response({
                'valid': False,
                'message': 'YAML配置为空'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            yaml_data = yaml.safe_load(yaml_content)

            # 验证环境YAML结构
            if not isinstance(yaml_data, dict):
                return Response({
                    'valid': False,
                    'message': 'YAML配置必须是字典格式'
                }, status=status.HTTP_400_BAD_REQUEST)

            # 检查是否有环境相关配置
            if 'environment' not in yaml_data and 'global' not in yaml_data:
                return Response({
                    'valid': False,
                    'message': 'YAML配置缺少environment或global配置项'
                }, status=status.HTTP_400_BAD_REQUEST)

            return Response({
                'valid': True,
                'message': 'YAML配置验证通过',
                'data': yaml_data
            }, status=status.HTTP_200_OK)

        except yaml.YAMLError as e:
            return Response({
                'valid': False,
                'message': f'YAML格式错误: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({
                'valid': False,
                'message': f'验证失败: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=False, methods=['post'])
    def format_yaml(self, request):
        """格式化环境YAML配置"""
        yaml_content = request.data.get('yaml_config', '')

        if not yaml_content.strip():
            return Response({
                'valid': False,
                'message': 'YAML配置为空'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            # 解析YAML
            yaml_data = yaml.safe_load(yaml_content)

            # 重新格式化
            formatted_yaml = yaml.dump(yaml_data, default_flow_style=False, allow_unicode=True, sort_keys=False)

            return Response({
                'valid': True,
                'message': 'YAML格式化成功',
                'formatted_yaml': formatted_yaml
            }, status=status.HTTP_200_OK)

        except yaml.YAMLError as e:
            return Response({
                'valid': False,
                'message': f'YAML格式错误: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({
                'valid': False,
                'message': f'格式化失败: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)


class TestCaseViewSet(viewsets.ModelViewSet):
    """测试用例管理视图集"""
    queryset = TestCase.objects.all()
    serializer_class = TestCaseSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['name','case_type', 'environment', 'is_active', 'created_by']
    search_fields = ['name', 'description']
    ordering_fields = ['name', 'created_at']
    ordering = ['-created_at']

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return TestCaseDetailSerializer
        return TestCaseSerializer

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)

    @action(detail=True, methods=['post'])
    def execute(self, request, pk=None):
        """执行测试用例"""
        test_case = self.get_object()

        # 创建执行记录
        execution = TestExecution.objects.create(
            test_case=test_case,
            environment=test_case.environment,
            status='pending',
            created_by=request.user
        )
        try:
            env = Environment.objects.get(id=test_case.environment_id).yaml_config
            env_config_dict = yaml.safe_load(env)
            runner = TestRunner(test_case.yaml_content, execution, env_config_dict)
            result = runner.run()
            return Response({
                'message': '测试执行完成',
                'execution_id': execution.id,
                'result': result
            }, status=status.HTTP_200_OK)
        except Exception as e:
            execution.status = 'error'
            execution.error_message = str(e)
            execution.finished_at = timezone.now()
            execution.save()
            return Response({
                'message': f'测试执行失败: {str(e)}',
                'execution_id': execution.id
            }, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=True, methods=['post'])
    def validate_yaml(self, request, pk=None):
        """验证YAML配置"""
        test_case = self.get_object()

        try:
            yaml_data = yaml.safe_load(test_case.yaml_content)

            # 验证YAML结构
            if 'case' in yaml_data:

                return Response({
                    'valid': True,
                    'message': 'YAML配置验证通过'
                }, status=status.HTTP_200_OK)
            else:
                return Response({
                    'valid': False,
                    'message': f'不存在case字段'
                }, status=status.HTTP_400_BAD_REQUEST)

        except yaml.YAMLError as e:
            return Response({
                'valid': False,
                'message': f'YAML格式错误: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({
                'valid': False,
                'message': f'验证失败: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)

    # def _run(self,yaml_tata,execution):


class TestExecutionViewSet(viewsets.ReadOnlyModelViewSet):
    """测试执行记录视图集"""
    queryset = TestExecution.objects.all()
    serializer_class = TestExecutionSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['status', 'test_case', 'environment', 'created_by']
    search_fields = ['test_case__name']
    ordering_fields = ['created_at', 'execution_time']
    ordering = ['-created_at']

    @action(detail=True, methods=['post'])
    def retry(self, request, pk=None):
        """重试执行"""
        execution = self.get_object()

        # 创建新的执行记录
        new_execution = TestExecution.objects.create(
            test_case=execution.test_case,
            environment=execution.environment,
            status='pending',
            created_by=request.user
        )

        try:
            env = Environment.objects.get(id=execution.test_case.environment_id).yaml_config
            env_config_dict = yaml.safe_load(env)
            runner = TestRunner(execution.test_case.yaml_content, new_execution,env_config_dict)
            result = runner.run()

            return Response({
                'message': '重试执行完成',
                'execution_id': new_execution.id,
                'result': result
            }, status=status.HTTP_200_OK)

        except Exception as e:
            new_execution.status = 'error'
            new_execution.error_message = str(e)
            new_execution.finished_at = timezone.now()
            new_execution.save()

            return Response({
                'message': f'重试执行失败: {str(e)}',
                'execution_id': new_execution.id
            }, status=status.HTTP_400_BAD_REQUEST)


class TestReportViewSet(viewsets.ReadOnlyModelViewSet):
    """测试报告视图集"""
    queryset = TestReport.objects.all()
    serializer_class = TestReportSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['created_by']
    search_fields = ['name', 'description']
    ordering_fields = ['created_at', 'success_rate']
    ordering = ['-created_at']

    @action(detail=False, methods=['post'])
    def generate_report(self, request):
        """生成测试报告"""
        execution_ids = request.data.get('execution_ids', [])

        if not execution_ids:
            return Response({
                'message': '请选择要生成报告的测试执行记录'
            }, status=status.HTTP_400_BAD_REQUEST)

        executions = TestExecution.objects.filter(id__in=execution_ids)

        if not executions.exists():
            return Response({
                'message': '未找到指定的测试执行记录'
            }, status=status.HTTP_400_BAD_REQUEST)

        # 统计结果
        total_cases = executions.count()
        passed_cases = executions.filter(status='passed').count()
        failed_cases = executions.filter(status='failed').count()
        error_cases = executions.filter(status='error').count()

        # 计算成功率
        success_rate = (passed_cases / total_cases * 100) if total_cases > 0 else 0

        # 创建报告
        report = TestReport.objects.create(
            name=f'测试报告_{timezone.now().strftime("%Y%m%d_%H%M%S")}',
            description=f'包含 {total_cases} 个测试用例的执行报告',
            total_cases=total_cases,
            passed_cases=passed_cases,
            failed_cases=failed_cases,
            error_cases=error_cases,
            success_rate=success_rate,
            execution_details={
                'execution_ids': list(executions.values_list('id', flat=True)),
                'summary': {
                    'total': total_cases,
                    'passed': passed_cases,
                    'failed': failed_cases,
                    'error': error_cases,
                    'success_rate': success_rate
                }
            },
            created_by=request.user
        )

        return Response({
            'message': '测试报告生成成功',
            'report_id': report.id,
            'summary': {
                'total': total_cases,
                'passed': passed_cases,
                'failed': failed_cases,
                'error': error_cases,
                'success_rate': success_rate
            }
        }, status=status.HTTP_201_CREATED)


class RegisterView(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        if not username or not password:
            return Response({'message': '用户名和密码不能为空'}, status=status.HTTP_400_BAD_REQUEST)
        if User.objects.filter(username=username).exists():
            return Response({'message': '用户名已存在'}, status=status.HTTP_400_BAD_REQUEST)
        user = User.objects.create_user(username=username, password=password)
        return Response({'user': {'id': user.id, 'username': user.username}}, status=status.HTTP_201_CREATED)


class LoginView(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        if not username or not password:
            return Response({'message': '用户名和密码不能为空'}, status=status.HTTP_400_BAD_REQUEST)
        user = authenticate(username=username, password=password)
        if user is not None:
            # 生成JWT token
            refresh = RefreshToken.for_user(user)
            return Response({
                'user': {
                    'id': user.id,
                    'username': user.username,
                    'email': user.email,
                    'first_name': user.first_name,
                    'last_name': user.last_name,
                },
                'access': str(refresh.access_token),
                'refresh': str(refresh)
            }, status=status.HTTP_200_OK)
        else:
            return Response({'message': '用户名或密码错误'}, status=status.HTTP_400_BAD_REQUEST)


class DailyLogViewSet(viewsets.ModelViewSet):
    queryset = DailyLog.objects.all().order_by('-created_at')
    serializer_class = DailyLogSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = [
        'name', 'tester', 'demand_time', 'version', 'module', 'product', 'review_time',
        'status', 'test_time', 'test_date', 'launch_time'
    ]
    search_fields = ['name', 'tester', 'version', 'module', 'product']
    ordering_fields = ['created_at', 'test_date', 'launch_time']

    def get_queryset(self):
        queryset = super().get_queryset()
        test_date_start = self.request.query_params.get('test_date_start')
        test_date_end = self.request.query_params.get('test_date_end')
        launch_time_start = self.request.query_params.get('launch_time_start')
        launch_time_end = self.request.query_params.get('launch_time_end')
        if test_date_start and test_date_end:
            queryset = queryset.filter(test_date__range=[test_date_start, test_date_end])
        if launch_time_start and launch_time_end:
            queryset = queryset.filter(launch_time__range=[launch_time_start, launch_time_end])
        return queryset

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        queryset = self.filter_queryset(self.get_queryset())
        # 统计需求规模和测试工时总和（如为数字可直接Sum，否则为字符串需特殊处理）
        try:
            demand_time_total = queryset.aggregate(total=models.Sum(models.Case(
                models.When(demand_time__regex=r'^\\d+$', then=models.Cast('demand_time', models.IntegerField())),
                default=0,
                output_field=models.IntegerField()
            )))['total'] or 0
            test_time_total = queryset.aggregate(total=models.Sum(models.Case(
                models.When(test_time__regex=r'^\\d+$', then=models.Cast('test_time', models.IntegerField())),
                default=0,
                output_field=models.IntegerField()
            )))['total'] or 0
        except Exception:
            demand_time_total = 0
            test_time_total = 0
        response.data['demand_time_total'] = demand_time_total
        response.data['test_time_total'] = test_time_total
        return response
